//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//
/******************************************************************************
**
**  COPYRIGHT (C) 2004 Intel Corporation.
**
**  This software as well as the software described in it is furnished under
**  license and may only be used or copied in accordance with the terms of the
**  license. The information in this file is furnished for informational use
**  only, is subject to change without notice, and should not be construed as
**  a commitment by Intel Corporation. Intel Corporation assumes no
**  responsibility or liability for any errors or inaccuracies that may appear
**  in this document or any software that may be provided in association with
**  this document. 
**  Except as permitted by such license, no part of this document may be 
**  reproduced, stored in a retrieval system, or transmitted in any form or by
**  any means without the express written consent of Intel Corporation. 
**
**  FILENAME:  xllp_lcd_zl_ls037v7dw01.c
**
**  PURPOSE:   platform-specific source file for XLLP LCD controller.
**				This file is specific for LS037V7DW01 (VGA/QVGA) on Littleton. 
**
*******************************************************************************/

#include "xllp_lcd.h"
#include "xllp_lcd_cpu.h"
#include "xllp_lcd_plat.h"
#include "xllp_mfp.h"
#include "xllp_mfp_plat.h"
#include "xllp_gpio.h"
#include "xllp_gpio_plat.h"

#define VGA_WIDTH 480
#define VGA_HEIGHT 640
#define QVGA_WIDTH 240
#define QVGA_HEIGHT 320
#define OLED_WIDTH 128
#define OLED_HEIGHT 128

static void set_power_mode(struct XLLP_LCD_S *pXllpLCD, XLLP_UINT32_T power_mode);
static XLLP_STATUS_T init_pins(P_XLLP_LCD_T pXllpLCD);
static XLLP_STATUS_T mini_lcd_init_pins(P_XLLP_MINI_LCD_T pXllpMiniLCD, int is_on);
static void oled_reset(P_XLLP_LCD_T pXllpLCD);
static void oled_init_cmd(P_XLLP_LCD_T pXllpLCD);
static void oled_write_ram_cmd(P_XLLP_LCD_T pXllpLCD);
static void oled_set_power_mode(P_XLLP_LCD_T pXllpLCD, XLLP_UINT32_T power_mode);
static void oled_set_update_area(P_XLLP_LCD_T pXllpLCD,
									      XLLP_UINT32_T x1, XLLP_UINT32_T x2,
									      XLLP_UINT32_T y1, XLLP_UINT32_T y2);

tft_panel_t qvga_ls037 = 
{
	LCD_TFT,
	QVGA_WIDTH,
	QVGA_HEIGHT,
	set_power_mode,
	init_pins,
	mini_lcd_init_pins,
	// timing
	{
		0x27,	/* BLW */
		0x28,	/* ELW */
		0x3,	/* HSW */
		0x2,	/* BFW */
		0x2,	/* EFW */
		0x0,	/* VSW */
		/* PCD */
		{
			0xe,	/* 104M */
			0x16,	/* 156M */
			0x1e,	/* 208M */
			0x4,	/* 39M */
			0x8		/* D0CS 60M */
		}
	},
	{ 
		0,	/* OEP */
		1,	/* PCP */
		1,	/* HSP */
		1	/* VSP */
	}
};

tft_panel_t vga_ls037 = 
{
	LCD_TFT,
	VGA_WIDTH,
	VGA_HEIGHT,
	set_power_mode,
	init_pins,
	mini_lcd_init_pins,
	/* timing */
	{
		0x4f,	/* BLW */
		0x5f,	/* ELW */
		0x3,	/* HSW */
		0x2,	/* BFW */
		0x6,	/* EFW */
		0x0,	/* VSW */
		/* PCD */
		{
		//    The set of values derivd from the formula
		//  will cause slightly over drive of the LCD which
		//  lead to lighter dots on the screen. Here we 
		//  adjust the devider a little bigger to archive 
		//  better display effect under VGA mode.
		//	0x3,		/* 104M */
		//	0x4,		/* 156M */
		//	0x7,		/* 208M */
		//	0x1,		/* 39M */
		//	0x2			/* D0CS */
			0x5,		/* 104M */
			0x7,		/* 156M */
			0xa,		/* 208M */
			0x1,		/* 39M */
			0x3			/* D0CS */
		}
	},
	{ 
		0,	/* OEP */
		1,	/* PCP */
		1,	/* HSP */
		1	/* VSP */
	}
};

smart_panel_t oled_ssd1339 =
{
	LCD_SMART,
	OLED_WIDTH,
	OLED_HEIGHT,
	set_power_mode,
	OLED_WIDTH,
	OLED_HEIGHT,
	oled_reset,
	init_pins,
	oled_init_cmd,
	oled_write_ram_cmd,
	oled_set_power_mode,
	oled_set_update_area,
	/* timing */
	{
		30,	/* BLW: WR, RD pulse width */
		8,	/* ELW: A0, CS, setup/hold */
		10,	/* HSW: output hold */
		42,	/* PCD: command inhibit */
		2,	/* synchronous count */
	}
};

static const XLLP_UINT32_T lcd_mfp_list []={
	XLLP_MFP_L_DD_8_OFFSET,    
	XLLP_MFP_L_DD_9_OFFSET,   
	XLLP_MFP_L_DD_10_OFFSET,   
	XLLP_MFP_L_DD_11_OFFSET,   
	XLLP_MFP_L_DD_12_OFFSET,       
	XLLP_MFP_L_DD_13_OFFSET,       
	XLLP_MFP_L_DD_14_OFFSET,       
	XLLP_MFP_L_DD_15_OFFSET,       
	XLLP_MFP_L_DD_16_OFFSET,       
	XLLP_MFP_L_DD_0_OFFSET,   
	XLLP_MFP_L_DD_1_OFFSET,   
	XLLP_MFP_L_DD_2_OFFSET,     
	XLLP_MFP_L_DD_3_OFFSET,      
	XLLP_MFP_L_DD_4_OFFSET,      
	XLLP_MFP_L_DD_5_OFFSET,       
	XLLP_MFP_L_DD_6_OFFSET,       
	XLLP_MFP_L_DD_7_OFFSET,      
	XLLP_MFP_L_FCLK_OFFSET,       
	XLLP_MFP_L_LCLK_OFFSET,         
	XLLP_MFP_L_PCLK_OFFSET,       
	XLLP_MFP_L_BIAS_OFFSET,
	
	XLLP_MFP_BACKLIGHT_PWM_OFFSET,	
	XLLP_MFP_L_DD_17_OFFSET,
	XLLP_MFP_L_VSYNC_OFFSET,
	XLLP_MFP_PIN_EOLIST_MARKER 
};

static const XLLP_MFP_ALT_FN_T lcd_af_list []={
	XLLP_MFP_L_DD_8_AF, 
	XLLP_MFP_L_DD_9_AF,
	XLLP_MFP_L_DD_10_AF,
	XLLP_MFP_L_DD_11_AF,   
	XLLP_MFP_L_DD_12_AF,   
	XLLP_MFP_L_DD_13_AF,   
	XLLP_MFP_L_DD_14_AF,   
	XLLP_MFP_L_DD_15_AF,   
	XLLP_MFP_L_DD_16_AF,   
	XLLP_MFP_L_DD_0_AF,   
	XLLP_MFP_L_DD_1_AF,   
	XLLP_MFP_L_DD_2_AF,   
	XLLP_MFP_L_DD_3_AF,   
	XLLP_MFP_L_DD_4_AF,   
	XLLP_MFP_L_DD_5_AF,   
	XLLP_MFP_L_DD_6_AF,   
	XLLP_MFP_L_DD_7_AF,   
	XLLP_MFP_L_FCLK_AF,     
	XLLP_MFP_L_LCLK_AF,   
	XLLP_MFP_L_PCLK_AF,   
	XLLP_MFP_L_BIAS_AF,
	
	XLLP_MFP_ALT_FN_0,
	
	XLLP_MFP_ALT_FN_0,
	XLLP_MFP_ALT_FN_0
};

static const XLLP_MFP_ALT_FN_T mini_lcd_af_list []={
	XLLP_MFP_ALT_FN_1, 
	XLLP_MFP_ALT_FN_1,
	XLLP_MFP_ALT_FN_1,
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,      
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,     
	XLLP_MFP_ALT_FN_1,   
	XLLP_MFP_ALT_FN_1,   
	
	XLLP_MFP_ALT_FN_0,
	XLLP_MFP_ALT_FN_0,
	XLLP_MFP_ALT_FN_0
};

static const XLLP_MFP_DRIVE_STRENGTH_T lcd_ds_list []={
	XLLP_MFP_DS_01X,	//0
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//5
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//10
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//15
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_04X,	
	XLLP_MFP_DS_01X,	//20
	XLLP_MFP_DS_01X,	//21
	XLLP_MFP_DS_01X,	//22
	XLLP_MFP_DS_01X		//23
};

static const XLLP_MFP_DRIVE_STRENGTH_T oled_ds_list []={
	XLLP_MFP_DS_01X,	//0
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//5
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//10
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//15
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,
	XLLP_MFP_DS_01X,	
	XLLP_MFP_DS_01X,	//20
	XLLP_MFP_DS_01X,	//21
	XLLP_MFP_DS_01X,	//22
	XLLP_MFP_DS_01X		//23
};


static const XLLP_MFP_LPM_OUTPUT_T lcd_lpm_output_list []={
	XLLP_MFP_L_DD_8_LPM,    
	XLLP_MFP_L_DD_9_LPM,   
	XLLP_MFP_L_DD_10_LPM,   
	XLLP_MFP_L_DD_11_LPM,   
	XLLP_MFP_L_DD_12_LPM,       
	XLLP_MFP_L_DD_13_LPM,       
	XLLP_MFP_L_DD_14_LPM,       
	XLLP_MFP_L_DD_15_LPM,       
	XLLP_MFP_L_DD_16_LPM,       
	XLLP_MFP_L_DD_0_LPM,   
	XLLP_MFP_L_DD_1_LPM,   
	XLLP_MFP_L_DD_2_LPM,     
	XLLP_MFP_L_DD_3_LPM,      
	XLLP_MFP_L_DD_4_LPM,      
	XLLP_MFP_L_DD_5_LPM,       
	XLLP_MFP_L_DD_6_LPM,       
	XLLP_MFP_L_DD_7_LPM,      
	XLLP_MFP_L_FCLK_LPM,       
	XLLP_MFP_L_LCLK_LPM,         
	XLLP_MFP_L_PCLK_LPM,       
	XLLP_MFP_L_BIAS_LPM,	
	
	XLLP_MFP_BACKLIGHT_PWM_LPM,	
	XLLP_MFP_L_DD_17_LPM,
	XLLP_MFP_L_VSYNC_LPM
};

static XLLP_BOOL_T mfp_resource_managed = 0;
static XLLP_BOOL_T mfp_alt_fun_lcd = 0;
static XLLP_BOOL_T panel_is_leaded = 1;

static XLLP_STATUS_T init_pins(P_XLLP_LCD_T pXllpLCD)
{
	XLLP_STATUS_T status = 0;
	XLLP_LEVEL_T mode_pin_level;
	XLLP_LEVEL_T lcd_select;
	P_XLLP_MFP_DRIVE_STRENGTH_T drive;
	
	mode_pin_level = pXllpLCD->panel->tft.width == VGA_WIDTH? XLLP_HI : XLLP_LO;

	// mode pin level is reverted for lead free panel
	if (!panel_is_leaded)
		mode_pin_level = mode_pin_level == XLLP_HI? XLLP_LO : XLLP_HI;

	lcd_select = pXllpLCD->panel->tft.width == OLED_WIDTH? XLLP_HI : XLLP_LO;

	if (!mfp_resource_managed)
	{
		status =  XllpMfpResourceManager_List(pXllpLCD->pMfpRmDb, 
											  (P_XLLP_UINT32_T)lcd_mfp_list, 
											  XLLP_MFP_RM_ID_XLLP_LCD, 
											  XLLP_SET);

		if ( XLLP_STATUS_SUCCESS != status)
		{
			goto err1;
		}

		mfp_resource_managed = 1;
	}
    // Lock MFPR block until finished with all MFPRs.
    // Don't forget to unlock for early returns, too.
    
	

	drive = (P_XLLP_MFP_DRIVE_STRENGTH_T)(lcd_select == XLLP_HI? oled_ds_list : lcd_ds_list);
		// Initialize the MFP registers for proper LCD Controller operation
		status =  XllpMfpSetAfDs_List((P_XLLP_VUINT32_T)(pXllpLCD->MFP), 
									  (P_XLLP_UINT32_T)lcd_mfp_list, 
									  (P_XLLP_MFP_ALT_FN_T)lcd_af_list, 
									  (P_XLLP_MFP_DRIVE_STRENGTH_T)drive);
		if (status != XLLP_STATUS_SUCCESS)
			goto err1;
			
		status = XllpMfpActivatePullUpDown_List((P_XLLP_VUINT32_T)(pXllpLCD->MFP),
                								(P_XLLP_UINT32_T)lcd_mfp_list,
                								 XLLP_OFF);
		if (status != XLLP_STATUS_SUCCESS)
			goto err1;

		// XllpGpioSetDirection((P_XLLP_GPIO_T)(pXllpLCD->GPIO), 14, XLLP_GPIO_DIRECTION_OUT);


		mfp_alt_fun_lcd = 1;


	// GPIO registers can't be retained after wakeup
	XllpGpioSetDirection((P_XLLP_GPIO_T)(pXllpLCD->GPIO), XLLP_GPIO_L_DD_17, XLLP_GPIO_DIRECTION_OUT);
	XllpGpioSetDirection((P_XLLP_GPIO_T)(pXllpLCD->GPIO), XLLP_GPIO_L_VSYNC, XLLP_GPIO_DIRECTION_OUT);
	XllpGpioSetOutputLevel((P_XLLP_GPIO_T)(pXllpLCD->GPIO), XLLP_GPIO_L_DD_17, lcd_select);
	XllpGpioSetOutputLevel((P_XLLP_GPIO_T)(pXllpLCD->GPIO), XLLP_GPIO_L_VSYNC, mode_pin_level);

err1:
	return status;	    
}

static void set_power_mode(struct XLLP_LCD_S *pXllpLCD, XLLP_UINT32_T power_mode)
{
    if (power_mode == XLLP_FALSE)
        XllpGpioSetOutputLevel((P_XLLP_GPIO_T)(pXllpLCD->GPIO), XLLP_GPIO_L_VSYNC, XLLP_LO);
}

static XLLP_STATUS_T mini_lcd_init_pins(P_XLLP_MINI_LCD_T pXllpMiniLCD, int is_on)
{
	P_XLLP_MFP_ALT_FN_T af_list = (P_XLLP_MFP_ALT_FN_T) (is_on? mini_lcd_af_list : lcd_af_list);

	mfp_alt_fun_lcd = 0;
	// Initialize the MFP registers for proper LCD Controller operation
	return XllpMfpSetAfDs_List((P_XLLP_VUINT32_T)(pXllpMiniLCD->MFP), 
	 				    (P_XLLP_UINT32_T)lcd_mfp_list, 
						af_list, 
						(P_XLLP_MFP_DRIVE_STRENGTH_T)lcd_ds_list
						);
}

void XllpLCDInit_VGA_QVGA_OLED(P_XLLP_LCD_T pXllpLCD, int mode, int is_leaded)
{
	if (mode == MODE_VGA)
		pXllpLCD->panel = (lcd_panel_t*)&vga_ls037;
	else if (mode == MODE_QVGA)
		pXllpLCD->panel = (lcd_panel_t*)&qvga_ls037;
	else if (mode == MODE_OLED)
		pXllpLCD->panel = (lcd_panel_t*)&oled_ssd1339;
	panel_is_leaded = is_leaded;

	if (!is_leaded)
	{
		qvga_ls037.timing.BLW = 0x14;
		qvga_ls037.timing.EFW = 0x3;
        vga_ls037.timing.EFW = 0x5;
	}
}

void XllpMiniLCDInit_VGA_QVGA_OLED(P_XLLP_MINI_LCD_T pXllpMiniLCD, int mode, int is_leaded)
{
	if (mode == MODE_VGA)
		pXllpMiniLCD->panel = &vga_ls037;
	else
		pXllpMiniLCD->panel = &qvga_ls037;

	panel_is_leaded = is_leaded;
}

static unsigned char rotate_8b(unsigned char c)
{
	char c1 = c << 2;

	return c1 | (c >> 6);
}

static cmd_out(P_XLLP_LCD_T pXllpLCD, XLLP_UINT8_T cmd)
{
	XLLP_UINT16_T lcd_cmd = (XLLP_UINT16_T)XLLP_MAKEUP_CMD(rotate_8b(cmd));
	SmartLoadCommand(pXllpLCD, &lcd_cmd, 1);
}

static data_out(P_XLLP_LCD_T pXllpLCD, XLLP_UINT8_T data)
{
	XLLP_UINT16_T lcd_cmd = (XLLP_UINT16_T)XLLP_MAKEUP_DATA(rotate_8b(data));
	SmartLoadCommand(pXllpLCD, &lcd_cmd, 1);
}

static void oled_reset(P_XLLP_LCD_T pXllpLCD)
{
	return;
}

void clear2(P_XLLP_LCD_T pXllpLCD)
{
	cmd_out(pXllpLCD, 0x8e);
	data_out(pXllpLCD, 0x0);
	data_out(pXllpLCD, 0x0);
	data_out(pXllpLCD, 0x70);
	data_out(pXllpLCD, 0x70);
	SmartSendCommand(pXllpLCD);
}

void set_line(P_XLLP_LCD_T pXllpLCD, int i)
{
	cmd_out(pXllpLCD, 0x75);		// row address
	data_out(pXllpLCD, i);			// start
	data_out(pXllpLCD, 59);			// end

	cmd_out(pXllpLCD, 0x15);		// column address
	data_out(pXllpLCD, 0);			// start
	data_out(pXllpLCD, 59);			// end

	cmd_out(pXllpLCD, 0x5c);
	SmartSendCommand(pXllpLCD);
}

void fill(P_XLLP_LCD_T pXllpLCD)
{
	int i = 0, j, k;


	for (k = 0; k < 15; k++)
	{
	set_line(pXllpLCD, k * 2);
	for (i = 0; i < 2; i++)
	{


		data_out(pXllpLCD, 0x0);
		data_out(pXllpLCD, 0x0);
		data_out(pXllpLCD, 0xff);
		for (j = 0; j < 118; j++)
		{
			data_out(pXllpLCD, 0xff);
			data_out(pXllpLCD, 0x0);
			data_out(pXllpLCD, 0x0);
		}
		data_out(pXllpLCD, 0x0);
		data_out(pXllpLCD, 0xff);
		data_out(pXllpLCD, 0x0);
	}
	
	SmartSendCommand(pXllpLCD);
	}
}

void clear(P_XLLP_LCD_T pXllpLCD)
{
	int i, j;
	cmd_out(pXllpLCD, 0x15);		// column address
	data_out(pXllpLCD, 0x0);			// start
	data_out(pXllpLCD, 0x7f);			// end

	cmd_out(pXllpLCD, 0x75);		// row address
	data_out(pXllpLCD, 0);			// start
	data_out(pXllpLCD, 0x7f);			// end

	cmd_out(pXllpLCD, 0x5c);

//	cmd_out(pXllpLCD, 0x5c);
	SmartSendCommand(pXllpLCD);

	for (j = 0; j < 10; j++)
	{
		for (i = 0; i < 40; i++)
		{
			data_out(pXllpLCD, 0xff);
		}
		SmartSendCommand(pXllpLCD);
	}

}

static void oled_init_cmd(P_XLLP_LCD_T pXllpLCD)
{
	//int i;
	cmd_out(pXllpLCD, 0xae);	// display off

	cmd_out(pXllpLCD, 0xca);	// set mux ratio
	data_out(pXllpLCD, 0x7f);	// 1/128 duty

	cmd_out(pXllpLCD, 0xa1);	// display start line
	data_out(pXllpLCD, 0x00);	// start on 0

	cmd_out(pXllpLCD, 0xa2);	// display offset
	data_out(pXllpLCD, 0x80);	// offset 128

	cmd_out(pXllpLCD, 0xa0);	// set remap and color depth
	data_out(pXllpLCD, 0xb4);	// 262k color, 8-bit MCU interface

	cmd_out(pXllpLCD, 0xc7);	// master current control
	data_out(pXllpLCD, 0x09);	// brightness: 0x3 low, 0x6 typical, 0x9 high
	
	cmd_out(pXllpLCD, 0xc1);	// set contrast level for R, G, B
	data_out(pXllpLCD, 0x6f);	// red
	data_out(pXllpLCD, 0x58);	// green
	data_out(pXllpLCD, 0x80);	// blue

	cmd_out(pXllpLCD, 0xb1);	// set reset and precharge period
	data_out(pXllpLCD, 0x1f);

	cmd_out(pXllpLCD, 0xb3);	// frame rate
	data_out(pXllpLCD, 0x10);	// 85Hz

	cmd_out(pXllpLCD, 0xbb);	// precharge level for R, G, B
	data_out(pXllpLCD, 0x00);	// red
	data_out(pXllpLCD, 0x00);	// green
	data_out(pXllpLCD, 0x00);	// blue

	cmd_out(pXllpLCD, 0xad);	// master configuration
	data_out(pXllpLCD, 0x8e);

	cmd_out(pXllpLCD, 0xb0);	// current saving
	data_out(pXllpLCD, 0x05);

	cmd_out(pXllpLCD, 0xa6);	// normal display
	cmd_out(pXllpLCD, 0xaf);	// display on

	SmartSendCommand(pXllpLCD);
}

static void oled_write_ram_cmd(P_XLLP_LCD_T pXllpLCD)
{
	cmd_out(pXllpLCD, 0x5c);
//	SmartSendCommand(pXllpLCD);
}

static void oled_set_power_mode(P_XLLP_LCD_T pXllpLCD, XLLP_UINT32_T power_mode)
{
    switch (power_mode)
    {
    case 0: //D0, Full On: full power,  full functionality
        cmd_out(pXllpLCD, 0xaf);
        cmd_out(pXllpLCD, 0xb0);	// current saving
        data_out(pXllpLCD, 0x12);
        break;
    case 1: //D1, Low Power On: fully functional at low power/performance
    case 2: //D2, Standby: partially powered with automatic wake
    case 3: //D3, Sleep: partially powered with device initiated wake
    case 4: //D4, Off: unpowered
        cmd_out(pXllpLCD, 0xae);
        break;
    default:break;
    }
    SmartSendCommand(pXllpLCD);
}

static void oled_set_update_area(P_XLLP_LCD_T pXllpLCD,
								   XLLP_UINT32_T x1,
								   XLLP_UINT32_T x2,
								   XLLP_UINT32_T y1,
								   XLLP_UINT32_T y2)
{
//	NKDbgPrintfW(L"oled_set_update_area+ %d, %d, %d, %d!\r\n", x1, x2, y1, y2);

	cmd_out(pXllpLCD, 0x15);		// column address
	data_out(pXllpLCD, (XLLP_UINT8_T)x1);			// start
	data_out(pXllpLCD, (XLLP_UINT8_T)x2);			// end

	cmd_out(pXllpLCD, 0x75);		// row address
	data_out(pXllpLCD, (XLLP_UINT8_T)y1);			// start
	data_out(pXllpLCD, (XLLP_UINT8_T)y2);			// end
}